{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "1623941a-664c-4c39-a8d5-ce6651cb7134",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Device: cuda:0\n",
      "Files already downloaded and verified\n",
      "Files already downloaded and verified\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "2024-06-03 17:32:06,043 - Epoch [1/20], Loss: 2.1799, Test Accuracy: 41.13 %\n",
      "2024-06-03 17:32:16,385 - Epoch [2/20], Loss: 2.0230, Test Accuracy: 50.98 %\n",
      "2024-06-03 17:32:26,567 - Epoch [3/20], Loss: 1.9488, Test Accuracy: 55.82 %\n",
      "2024-06-03 17:32:36,450 - Epoch [4/20], Loss: 1.8981, Test Accuracy: 59.51 %\n",
      "2024-06-03 17:32:46,240 - Epoch [5/20], Loss: 1.8603, Test Accuracy: 62.26 %\n",
      "2024-06-03 17:32:55,894 - Epoch [6/20], Loss: 1.8308, Test Accuracy: 63.52 %\n",
      "2024-06-03 17:33:05,582 - Epoch [7/20], Loss: 1.8047, Test Accuracy: 65.05 %\n",
      "2024-06-03 17:33:15,312 - Epoch [8/20], Loss: 1.7848, Test Accuracy: 66.69 %\n",
      "2024-06-03 17:33:24,877 - Epoch [9/20], Loss: 1.7673, Test Accuracy: 65.56 %\n",
      "2024-06-03 17:33:34,454 - Epoch [10/20], Loss: 1.7523, Test Accuracy: 68.49 %\n",
      "2024-06-03 17:33:44,046 - Epoch [11/20], Loss: 1.7400, Test Accuracy: 68.71 %\n",
      "2024-06-03 17:33:53,796 - Epoch [12/20], Loss: 1.7295, Test Accuracy: 69.40 %\n",
      "2024-06-03 17:34:03,598 - Epoch [13/20], Loss: 1.7175, Test Accuracy: 69.59 %\n",
      "2024-06-03 17:34:13,147 - Epoch [14/20], Loss: 1.7070, Test Accuracy: 70.17 %\n",
      "2024-06-03 17:34:22,961 - Epoch [15/20], Loss: 1.6984, Test Accuracy: 70.37 %\n",
      "2024-06-03 17:34:32,527 - Epoch [16/20], Loss: 1.6889, Test Accuracy: 70.60 %\n",
      "2024-06-03 17:34:42,315 - Epoch [17/20], Loss: 1.6815, Test Accuracy: 70.99 %\n",
      "2024-06-03 17:34:52,179 - Epoch [18/20], Loss: 1.6741, Test Accuracy: 71.26 %\n",
      "2024-06-03 17:35:01,801 - Epoch [19/20], Loss: 1.6660, Test Accuracy: 70.56 %\n",
      "2024-06-03 17:35:11,500 - Epoch [20/20], Loss: 1.6597, Test Accuracy: 71.03 %\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Finished Training\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAA90AAAHqCAYAAAAZLi26AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy81sbWrAAAACXBIWXMAAA9hAAAPYQGoP6dpAABfcElEQVR4nO3deVxU9f7H8feAsingrigoaqbmlpqaGi5lLpm7Zata3WzRyrrea3avmdbNbLu2apqppWbpRSvTTEvUTDNzSc21UEhAcwNXwOH8/jg/QISBARnODPN6Ph7nMTNnvufMZ5pGePP9nu/XZhiGIQAAAAAAUOx8rC4AAAAAAIDSitANAAAAAICLELoBAAAAAHARQjcAAAAAAC5C6AYAAAAAwEUI3QAAAAAAuAihGwAAAAAAFyF0AwAAAADgIoRuAAAAAABchNANAICHGD58uCIjI4t07AsvvCCbzVa8BQEAgAIRugEAuEo2m82pLSYmxupSLTF8+HCVL1/e6jIAALCEzTAMw+oiAADwZPPmzcvx+OOPP9aqVav0ySef5Nh/6623qnr16kV+nfT0dGVkZMjf37/Qx166dEmXLl1SQEBAkV+/qIYPH67Fixfr7NmzJf7aAABYrYzVBQAA4Onuu+++HI83bdqkVatW5dp/pfPnzysoKMjp1ylbtmyR6pOkMmXKqEwZfuwDAFDSGF4OAEAJ6NKli5o2bapffvlFnTp1UlBQkJ577jlJ0hdffKHevXurZs2a8vf3V/369fXiiy/KbrfnOMeV13QfOnRINptNr7/+umbMmKH69evL399fbdq00c8//5zj2Lyu6bbZbBo1apSWLl2qpk2byt/fX02aNNE333yTq/6YmBjdcMMNCggIUP369fXBBx8U+3XiixYtUuvWrRUYGKgqVarovvvu05EjR3K0SUpK0gMPPKDw8HD5+/srLCxM/fr106FDh7LabNmyRT169FCVKlUUGBiounXr6sEHHyy2OgEAKAz+5A0AQAk5ceKEevXqpbvuukv33Xdf1lDzOXPmqHz58nrmmWdUvnx5ff/993r++eeVkpKi1157rcDzLliwQGfOnNEjjzwim82mV199VQMHDtQff/xRYO/4Dz/8oOjoaD3++OMKDg7W22+/rUGDBikuLk6VK1eWJG3btk09e/ZUWFiYJk6cKLvdrkmTJqlq1apX/x/l/82ZM0cPPPCA2rRpo8mTJ+vo0aN66623tGHDBm3btk0VKlSQJA0aNEi7d+/WE088ocjISB07dkyrVq1SXFxc1uPu3buratWqevbZZ1WhQgUdOnRI0dHRxVYrAACFYgAAgGI1cuRI48ofsZ07dzYkGdOnT8/V/vz587n2PfLII0ZQUJBx8eLFrH3Dhg0z6tSpk/U4NjbWkGRUrlzZOHnyZNb+L774wpBkfPXVV1n7JkyYkKsmSYafn59x8ODBrH07duwwJBnvvPNO1r4+ffoYQUFBxpEjR7L2HThwwChTpkyuc+Zl2LBhRrly5Rw+n5aWZlSrVs1o2rSpceHChaz9y5YtMyQZzz//vGEYhnHq1ClDkvHaa685PNeSJUsMScbPP/9cYF0AAJQEhpcDAFBC/P399cADD+TaHxgYmHX/zJkzOn78uKKionT+/Hnt3bu3wPMOGTJEFStWzHocFRUlSfrjjz8KPLZbt26qX79+1uPmzZsrJCQk61i73a7Vq1erf//+qlmzZla7a665Rr169Srw/M7YsmWLjh07pscffzzHRG+9e/dWo0aN9PXXX0sy/zv5+fkpJiZGp06dyvNcmT3iy5YtU3p6erHUBwDA1SB0AwBQQmrVqiU/P79c+3fv3q0BAwYoNDRUISEhqlq1atYkbMnJyQWet3bt2jkeZwZwR8E0v2Mzj8889tixY7pw4YKuueaaXO3y2lcUhw8fliQ1bNgw13ONGjXKet7f319TpkzRihUrVL16dXXq1EmvvvqqkpKSstp37txZgwYN0sSJE1WlShX169dPs2fPVmpqarHUCgBAYRG6AQAoIZf3aGc6ffq0OnfurB07dmjSpEn66quvtGrVKk2ZMkWSlJGRUeB5fX1989xvOLEq6NUca4XRo0dr//79mjx5sgICAjR+/Hg1btxY27Ztk2RODrd48WJt3LhRo0aN0pEjR/Tggw+qdevWLFkGALAEoRsAAAvFxMToxIkTmjNnjp566indfvvt6tatW47h4laqVq2aAgICdPDgwVzP5bWvKOrUqSNJ2rdvX67n9u3bl/V8pvr16+vvf/+7vv32W+3atUtpaWl64403crS58cYb9Z///EdbtmzR/PnztXv3bi1cuLBY6gUAoDAI3QAAWCizp/nynuW0tDS9//77VpWUg6+vr7p166alS5cqISEha//Bgwe1YsWKYnmNG264QdWqVdP06dNzDANfsWKF9uzZo969e0sy1zW/ePFijmPr16+v4ODgrONOnTqVq5f++uuvlySGmAMALMGSYQAAWKhDhw6qWLGihg0bpieffFI2m02ffPKJWw3vfuGFF/Ttt9+qY8eOeuyxx2S32/Xuu++qadOm2r59u1PnSE9P10svvZRrf6VKlfT4449rypQpeuCBB9S5c2fdfffdWUuGRUZG6umnn5Yk7d+/X7fccovuvPNOXXfddSpTpoyWLFmio0eP6q677pIkzZ07V++//74GDBig+vXr68yZM5o5c6ZCQkJ02223Fdt/EwAAnEXoBgDAQpUrV9ayZcv097//Xf/+979VsWJF3XfffbrlllvUo0cPq8uTJLVu3VorVqzQmDFjNH78eEVERGjSpEnas2ePU7OrS2bv/fjx43Ptr1+/vh5//HENHz5cQUFBeuWVVzR27FiVK1dOAwYM0JQpU7JmJI+IiNDdd9+t7777Tp988onKlCmjRo0a6fPPP9egQYMkmROpbd68WQsXLtTRo0cVGhqqtm3bav78+apbt26x/TcBAMBZNsOd/pQOAAA8Rv/+/bV7924dOHDA6lIAAHBbXNMNAAAKdOHChRyPDxw4oOXLl6tLly7WFAQAgIegpxsAABQoLCxMw4cPV7169XT48GFNmzZNqamp2rZtmxo0aGB1eQAAuC2u6QYAAAXq2bOnPv30UyUlJcnf31/t27fXyy+/TOAGAKAA9HQDAAAAAOAiXNMNAAAAAICLELoBAAAAAHARr7umOyMjQwkJCQoODpbNZrO6HAAAAACABzIMQ2fOnFHNmjXl4+O4P9vS0D158mRFR0dr7969CgwMVIcOHTRlyhQ1bNjQ4TEzZ87Uxx9/rF27dkmSWrdurZdffllt27Z16jUTEhIUERFRLPUDAAAAALxbfHy8wsPDHT5vaeheu3atRo4cqTZt2ujSpUt67rnn1L17d/32228qV65cnsfExMTo7rvvVocOHRQQEKApU6aoe/fu2r17t2rVqlXgawYHB0sy/8OEhIQU6/sBAAAAAHiHlJQURUREZGVMR9xq9vK//vpL1apV09q1a9WpUyenjrHb7apYsaLeffddDR06tMD2KSkpCg0NVXJyMqEbAAAAAFAkzmZLt5pILTk5WZJUqVIlp485f/680tPTC3UMAAAAAAAlwW0mUsvIyNDo0aPVsWNHNW3a1Onjxo4dq5o1a6pbt255Pp+amqrU1NSsxykpKVddKwAAAAAAznCbnu6RI0dq165dWrhwodPHvPLKK1q4cKGWLFmigICAPNtMnjxZoaGhWRuTqAEAAAAASopbXNM9atQoffHFF1q3bp3q1q3r1DGvv/66XnrpJa1evVo33HCDw3Z59XRHRERwTTcAAADg5ex2u9LT060uA26qbNmy8vX1dfi8s9d0Wzq83DAMPfHEE1qyZIliYmKcDtyvvvqq/vOf/2jlypX5Bm5J8vf3l7+/f3GUCwAAAKAUMAxDSUlJOn36tNWlwM1VqFBBNWrUkM1mK/I5LA3dI0eO1IIFC/TFF18oODhYSUlJkqTQ0FAFBgZKkoYOHapatWpp8uTJkqQpU6bo+eef14IFCxQZGZl1TPny5VW+fHlr3ggAAAAAj5EZuKtVq6agoKCrClQonQzD0Pnz53Xs2DFJUlhYWJHPZWnonjZtmiSpS5cuOfbPnj1bw4cPlyTFxcXJx8cnxzFpaWkaPHhwjmMmTJigF154wZXlAgAAAPBwdrs9K3BXrlzZ6nLgxjI7go8dO6Zq1arlO9Q8P5YPLy9ITExMjseHDh1yTTEAAAAASr3Ma7iDgoIsrgSeIPP/k/T09CKHbreZvRwAAAAASgpDyuGM4vj/hNANAAAAAICLELoBAAAAwEtFRkZq6tSpTrePiYmRzWZj5vdCIHS7IbtdiomRPv3UvLXbra4IAAAAwJVK8vd2m82W71bUSaV//vlnjRgxwun2HTp0UGJiokJDQ4v0es4qTeHe0onUkFt0tPTUU9Kff2bvCw+X3npLGjjQuroAAAAAZCvp39sTExOz7n/22Wd6/vnntW/fvqx9ly+fbBiG7Ha7ypQpOO5VrVq1UHX4+fmpRo0ahTrG29HT7Uaio6XBg3N+cSXpyBFzf3S0NXUBAAAAyGbF7+01atTI2kJDQ2Wz2bIe7927V8HBwVqxYoVat24tf39//fDDD/r999/Vr18/Va9eXeXLl1ebNm20evXqHOe9cni5zWbThx9+qAEDBigoKEgNGjTQl19+mfX8lT3Qc+bMUYUKFbRy5Uo1btxY5cuXV8+ePXP8keDSpUt68sknVaFCBVWuXFljx47VsGHD1L9//yL/9zh16pSGDh2qihUrKigoSL169dKBAweynj98+LD69OmjihUrqly5cmrSpImWL1+edey9996rqlWrKjAwUA0aNNDs2bOLXEtBCN1uwm43/1KW1ypqmftGj2aoOQAAAFDcDEM6d865LSVFevLJ/H9vf+ops50z53NiFWWnPfvss3rllVe0Z88eNW/eXGfPntVtt92m7777Ttu2bVPPnj3Vp08fxcXF5XueiRMn6s4779Svv/6q2267Tffee69OnjzpsP358+f1+uuv65NPPtG6desUFxenMWPGZD0/ZcoUzZ8/X7Nnz9aGDRuUkpKipUuXXtV7HT58uLZs2aIvv/xSGzdulGEYuu2227KWhBs5cqRSU1O1bt067dy5U1OmTMkaDTB+/Hj99ttvWrFihfbs2aNp06apSpUqV1VPfhhe7ibWr8/9l7LLGYYUH2+269KlxMoCAAAASr3z56XLRmdfFcMwf6939pLns2elcuWK57UnTZqkW2+9NetxpUqV1KJFi6zHL774opYsWaIvv/xSo0aNcnie4cOH6+6775Ykvfzyy3r77be1efNm9ezZM8/26enpmj59uurXry9JGjVqlCZNmpT1/DvvvKNx48ZpwIABkqR33303q9e5KA4cOKAvv/xSGzZsUIcOHSRJ8+fPV0REhJYuXao77rhDcXFxGjRokJo1ayZJqlevXtbxcXFxatmypW644QZJZm+/K9HT7SYuG31RLO0AAAAAeJfMEJnp7NmzGjNmjBo3bqwKFSqofPny2rNnT4E93c2bN8+6X65cOYWEhOjYsWMO2wcFBWUFbkkKCwvLap+cnKyjR4+qbdu2Wc/7+vqqdevWhXpvl9uzZ4/KlCmjdu3aZe2rXLmyGjZsqD179kiSnnzySb300kvq2LGjJkyYoF9//TWr7WOPPaaFCxfq+uuv1z//+U/9+OOPRa7FGYRuNxEWVrztAAAAADgnKMjscXZmc7aDdvly584XFFR876PcFV3mY8aM0ZIlS/Tyyy9r/fr12r59u5o1a6a0tLR8z1O2bNkcj202mzIyMgrV3ijOcfNF8Le//U1//PGH7r//fu3cuVM33HCD3nnnHUlSr169dPjwYT399NNKSEjQLbfckmM4fHEjdLuJqChztkObLe/nbTYpIsJsBwAAAKD42GzmEG9ntu7dnfu9vXt3587n6DzFYcOGDRo+fLgGDBigZs2aqUaNGjp06JDrXjAPoaGhql69un7+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uAihGwAAAAAAFyF0AwAAAADgIoRuAAAAAABchNANAAAAAICLlLG6gJJmGIYkKSUlxeJKAAAAAACeKjNTZmZMR7wudJ85c0aSFBERYXElAAAAAABPd+bMGYWGhjp83mYUFMtLmYyMDCUkJCg4OFg2m83qclCAlJQURUREKD4+XiEhIVaXAyfxuXkmPjfPxOfmmfjcPA+fmWfic/NMnvK5GYahM2fOqGbNmvLxcXzlttf1dPv4+Cg8PNzqMlBIISEhbv2FQ9743DwTn5tn4nPzTHxunofPzDPxuXkmT/jc8uvhzsREagAAAAAAuAihGwAAAAAAFyF0w635+/trwoQJ8vf3t7oUFAKfm2fic/NMfG6eic/N8/CZeSY+N89U2j43r5tIDQAAAACAkkJPNwAAAAAALkLoBgAAAADARQjdAAAAAAC4CKEblpk8ebLatGmj4OBgVatWTf3799e+ffvyPWbOnDmy2Ww5toCAgBKqGJL0wgsv5PoMGjVqlO8xixYtUqNGjRQQEKBmzZpp+fLlJVQtMkVGRub63Gw2m0aOHJlne75r1li3bp369OmjmjVrymazaenSpTmeNwxDzz//vMLCwhQYGKhu3brpwIEDBZ73vffeU2RkpAICAtSuXTtt3rzZRe/AO+X3uaWnp2vs2LFq1qyZypUrp5o1a2ro0KFKSEjI95xF+bcWhVPQ92348OG5PoOePXsWeF6+b65V0OeW1886m82m1157zeE5+b65ljO/81+8eFEjR45U5cqVVb58eQ0aNEhHjx7N97xF/ZloBUI3LLN27VqNHDlSmzZt0qpVq5Senq7u3bvr3Llz+R4XEhKixMTErO3w4cMlVDEyNWnSJMdn8MMPPzhs++OPP+ruu+/WQw89pG3btql///7q37+/du3aVYIV4+eff87xma1atUqSdMcddzg8hu9ayTt37pxatGih9957L8/nX331Vb399tuaPn26fvrpJ5UrV049evTQxYsXHZ7zs88+0zPPPKMJEyZo69atatGihXr06KFjx4656m14nfw+t/Pnz2vr1q0aP368tm7dqujoaO3bt099+/Yt8LyF+bcWhVfQ902SevbsmeMz+PTTT/M9J9831yvoc7v880pMTNRHH30km82mQYMG5Xtevm+u48zv/E8//bS++uorLVq0SGvXrlVCQoIGDhyY73mL8jPRMgbgJo4dO2ZIMtauXeuwzezZs43Q0NCSKwq5TJgwwWjRooXT7e+8806jd+/eOfa1a9fOeOSRR4q5MhTGU089ZdSvX9/IyMjI83m+a9aTZCxZsiTrcUZGhlGjRg3jtddey9p3+vRpw9/f3/j0008dnqdt27bGyJEjsx7b7XajZs2axuTJk11St7e78nPLy+bNmw1JxuHDhx22Key/tbg6eX1uw4YNM/r161eo8/B9K1nOfN/69etn3Hzzzfm24ftWsq78nf/06dNG2bJljUWLFmW12bNnjyHJ2LhxY57nKOrPRKvQ0w23kZycLEmqVKlSvu3Onj2rOnXqKCIiQv369dPu3btLojxc5sCBA6pZs6bq1aune++9V3FxcQ7bbty4Ud26dcuxr0ePHtq4caOry4QDaWlpmjdvnh588EHZbDaH7fiuuZfY2FglJSXl+D6FhoaqXbt2Dr9PaWlp+uWXX3Ic4+Pjo27duvEdtFBycrJsNpsqVKiQb7vC/FsL14iJiVG1atXUsGFDPfbYYzpx4oTDtnzf3M/Ro0f19ddf66GHHiqwLd+3knPl7/y//PKL0tPTc3x3GjVqpNq1azv87hTlZ6KVCN1wCxkZGRo9erQ6duyopk2bOmzXsGFDffTRR/riiy80b948ZWRkqEOHDvrzzz9LsFrv1q5dO82ZM0fffPONpk2bptjYWEVFRenMmTN5tk9KSlL16tVz7KtevbqSkpJKolzkYenSpTp9+rSGDx/usA3fNfeT+Z0pzPfp+PHjstvtfAfdyMWLFzV27FjdfffdCgkJcdiusP/Wovj17NlTH3/8sb777jtNmTJFa9euVa9evWS32/Nsz/fN/cydO1fBwcEFDlPm+1Zy8vqdPykpSX5+frn+EJnfd6coPxOtVMbqAgBJGjlypHbt2lXg9TPt27dX+/btsx536NBBjRs31gcffKAXX3zR1WVCUq9evbLuN2/eXO3atVOdOnX0+eefO/WXZFhv1qxZ6tWrl2rWrOmwDd81oPilp6frzjvvlGEYmjZtWr5t+bfWenfddVfW/WbNmql58+aqX7++YmJidMstt1hYGZz10Ucf6d577y1wIlC+byXH2d/5Sxt6umG5UaNGadmyZVqzZo3Cw8MLdWzZsmXVsmVLHTx40EXVoSAVKlTQtdde6/AzqFGjRq7ZJ48ePaoaNWqURHm4wuHDh7V69Wr97W9/K9RxfNesl/mdKcz3qUqVKvL19eU76AYyA/fhw4e1atWqfHu581LQv7VwvXr16qlKlSoOPwO+b+5l/fr12rdvX6F/3kl831zF0e/8NWrUUFpamk6fPp2jfX7fnaL8TLQSoRuWMQxDo0aN0pIlS/T999+rbt26hT6H3W7Xzp07FRYW5oIK4YyzZ8/q999/d/gZtG/fXt99912OfatWrcrRi4qSM3v2bFWrVk29e/cu1HF816xXt25d1ahRI8f3KSUlRT/99JPD75Ofn59at26d45iMjAx99913fAdLUGbgPnDggFavXq3KlSsX+hwF/VsL1/vzzz914sQJh58B3zf3MmvWLLVu3VotWrQo9LF834pXQb/zt27dWmXLls3x3dm3b5/i4uIcfneK8jPRUhZP5AYv9thjjxmhoaFGTEyMkZiYmLWdP38+q839999vPPvss1mPJ06caKxcudL4/fffjV9++cW46667jICAAGP37t1WvAWv9Pe//92IiYkxYmNjjQ0bNhjdunUzqlSpYhw7dswwjNyf2YYNG4wyZcoYr7/+urFnzx5jwoQJRtmyZY2dO3da9Ra8lt1uN2rXrm2MHTs213N819zDmTNnjG3bthnbtm0zJBlvvvmmsW3btqxZrl955RWjQoUKxhdffGH8+uuvRr9+/Yy6desaFy5cyDrHzTffbLzzzjtZjxcuXGj4+/sbc+bMMX777TdjxIgRRoUKFYykpKQSf3+lVX6fW1pamtG3b18jPDzc2L59e46fd6mpqVnnuPJzK+jfWly9/D63M2fOGGPGjDE2btxoxMbGGqtXrzZatWplNGjQwLh48WLWOfi+lbyC/p00DMNITk42goKCjGnTpuV5Dr5vJcuZ3/kfffRRo3bt2sb3339vbNmyxWjfvr3Rvn37HOdp2LChER0dnfXYmZ+J7oLQDctIynObPXt2VpvOnTsbw4YNy3o8evRoo3bt2oafn59RvXp147bbbjO2bt1a8sV7sSFDhhhhYWGGn5+fUatWLWPIkCHGwYMHs56/8jMzDMP4/PPPjWuvvdbw8/MzmjRpYnz99dclXDUMwzBWrlxpSDL27duX6zm+a+5hzZo1ef67mPnZZGRkGOPHjzeqV69u+Pv7G7fcckuuz7NOnTrGhAkTcux75513sj7Ptm3bGps2bSqhd+Qd8vvcYmNjHf68W7NmTdY5rvzcCvq3Flcvv8/t/PnzRvfu3Y2qVasaZcuWNerUqWM8/PDDucIz37eSV9C/k4ZhGB988IERGBhonD59Os9z8H0rWc78zn/hwgXj8ccfNypWrGgEBQUZAwYMMBITE3Od5/JjnPmZ6C5shmEYrulDBwAAAADAu3FNNwAAAAAALkLoBgAAAADARQjdAAAAAAC4CKEbAAAAAAAXIXQDAAAAAOAihG4AAAAAAFyE0A0AAAAAgIsQugEAAAAAcBFCNwAAKDY2m01Lly61ugwAANwGoRsAgFJi+PDhstlsubaePXtaXRoAAF6rjNUFAACA4tOzZ0/Nnj07xz5/f3+LqgEAAPR0AwBQivj7+6tGjRo5tooVK0oyh35PmzZNvXr1UmBgoOrVq6fFixfnOH7nzp26+eabFRgYqMqVK2vEiBE6e/ZsjjYfffSRmjRpIn9/f4WFhWnUqFE5nj9+/LgGDBigoKAgNWjQQF9++aVr3zQAAG6M0A0AgBcZP368Bg0apB07dujee+/VXXfdpT179kiSzp07px49eqhixYr6+eeftWjRIq1evTpHqJ42bZpGjhypESNGaOfOnfryyy91zTXX5HiNiRMn6s4779Svv/6q2267Tffee69OnjxZou8TAAB3YTMMw7C6CAAAcPWGDx+uefPmKSAgIMf+5557Ts8995xsNpseffRRTZs2Leu5G2+8Ua1atdL777+vmTNnauzYsYqPj1e5cuUkScuXL1efPn2UkJCg6tWrq1atWnrggQf00ksv5VmDzWbTv//9b7344ouSzCBfvnx5rVixgmvLAQBeiWu6AQAoRbp27ZojVEtSpUqVsu63b98+x3Pt27fX9u3bJUl79uxRixYtsgK3JHXs2FEZGRnat2+fbDabEhISdMstt+RbQ/PmzbPulytXTiEhITp27FhR3xIAAB6N0A0AQClSrly5XMO9i0tgYKBT7cqWLZvjsc1mU0ZGhitKAgDA7XFNNwAAXmTTpk25Hjdu3FiS1LhxY+3YsUPnzp3Len7Dhg3y8fFRw4YNFRwcrMjISH333XclWjMAAJ6Mnm4AAEqR1NRUJSUl5dhXpkwZValSRZK0aNEi3XDDDbrppps0f/58bd68WbNmzZIk3XvvvZowYYKGDRumF154QX/99ZeeeOIJ3X///apevbok6YUXXtCjjz6qatWqqVevXjpz5ow2bNigJ554omTfKAAAHoLQDQBAKfLNN98oLCwsx76GDRtq7969ksyZxRcuXKjHH39cYWFh+vTTT3XddddJkoKCgrRy5Uo99dRTatOmjYKCgjRo0CC9+eabWecaNmyYLl68qP/+978aM2aMqlSposGDB5fcGwQAwMMwezkAAF7CZrNpyZIl6t+/v9WlAADgNbimGwAAAAAAFyF0AwAAAADgIlzTDQCAl+CKMgAASh493QAAAAAAuAihGwAAAAAAFyF0AwAAAADgIoRuAAAAAABchNANAAAAAICLELoBAAAAAHARQjcAAAAAAC5C6AYAAAAAwEUI3QAAAAAAuMj/Aehh3Mvuqhz7AAAAAElFTkSuQmCC",
      "text/plain": [
       "<Figure size 1000x500 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Final Test Accuracy: 71.03 %\n"
     ]
    }
   ],
   "source": [
    "#==========================================================================\n",
    "#此版本为使用Pytorch框架进行训练，设计了两个网络，一个较简单一个稍复杂，均与自己手写版中的网络一一对应。\n",
    "#但由于没有cuda加速，CPU运行太过缓慢，一个周期要8小时或40小时，所以自己手写版本可能只完成了5个周期或者一个周期都没有完成，只做到了可以运行，无法进行对比。\n",
    "#==========================================================================\n",
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.optim as optim\n",
    "import torchvision\n",
    "import torchvision.transforms as transforms\n",
    "import matplotlib.pyplot as plt\n",
    "import logging\n",
    "\n",
    "# 检查 GPU 是否可用\n",
    "device = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\n",
    "print(\"Device:\", device)\n",
    "\n",
    "# 设置日志\n",
    "logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(message)s')\n",
    "logger = logging.getLogger()\n",
    "\n",
    "# 定义自定义层\n",
    "class ConvLayer(nn.Module):\n",
    "    def __init__(self, out_channels, kernel_size, in_channels=3, stride=1, padding=0):\n",
    "        super(ConvLayer, self).__init__()\n",
    "        self.conv = nn.Conv2d(in_channels, out_channels, kernel_size, stride, padding)\n",
    "        self.relu = nn.ReLU()\n",
    "        self.bn = nn.BatchNorm2d(out_channels)\n",
    "    \n",
    "    def forward(self, x):\n",
    "        x = self.conv(x)\n",
    "        x = self.relu(x)\n",
    "        x = self.bn(x)\n",
    "        return x\n",
    "\n",
    "class MaxPoolLayer(nn.Module):\n",
    "    def __init__(self, kernel_size, stride):\n",
    "        super(MaxPoolLayer, self).__init__()\n",
    "        self.pool = nn.MaxPool2d(kernel_size, stride)\n",
    "    \n",
    "    def forward(self, x):\n",
    "        x = self.pool(x)\n",
    "        return x\n",
    "\n",
    "class DenseLayer(nn.Module):\n",
    "    def __init__(self, in_features, out_features, activation='relu'):\n",
    "        super(DenseLayer, self).__init__()\n",
    "        self.fc = nn.Linear(in_features, out_features)\n",
    "        if activation == 'relu':\n",
    "            self.activation = nn.ReLU()\n",
    "        elif activation == 'softmax':\n",
    "            self.activation = nn.Softmax(dim=1)\n",
    "        else:\n",
    "            self.activation = None\n",
    "    \n",
    "    def forward(self, x):\n",
    "        x = self.fc(x)\n",
    "        if self.activation:\n",
    "            x = self.activation(x)\n",
    "        return x\n",
    "\n",
    "# 定义新的 CNN 网络\n",
    "class CNN(nn.Module):\n",
    "    def __init__(self):\n",
    "        super(CNN, self).__init__()\n",
    "        self.conv1 = ConvLayer(32, 3, 3, stride=1, padding=1)\n",
    "        self.pool1 = MaxPoolLayer(2, 2)\n",
    "        self.conv2 = ConvLayer(64, 3, 32, stride=1, padding=1)\n",
    "        self.pool2 = MaxPoolLayer(2, 2)\n",
    "        self.fc1 = DenseLayer(8*8*64, 128, activation='relu')\n",
    "        self.fc2 = DenseLayer(128, 10, activation='softmax')\n",
    "        \n",
    "    def forward(self, x):\n",
    "        x = self.conv1(x)\n",
    "        x = self.pool1(x)\n",
    "        x = self.conv2(x)\n",
    "        x = self.pool2(x)\n",
    "        x = x.view(x.size(0), -1)  # 展平\n",
    "        x = self.fc1(x)\n",
    "        x = self.fc2(x)\n",
    "        return x\n",
    "\n",
    "# 加载 CIFAR-10 数据集\n",
    "transform = transforms.Compose(\n",
    "    [transforms.ToTensor(),\n",
    "     transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])\n",
    "\n",
    "trainset = torchvision.datasets.CIFAR10(root='./data', train=True,\n",
    "                                        download=True, transform=transform)\n",
    "trainloader = torch.utils.data.DataLoader(trainset, batch_size=100,\n",
    "                                          shuffle=True, num_workers=2)\n",
    "\n",
    "testset = torchvision.datasets.CIFAR10(root='./data', train=False,\n",
    "                                       download=True, transform=transform)\n",
    "testloader = torch.utils.data.DataLoader(testset, batch_size=100,\n",
    "                                         shuffle=False, num_workers=2)\n",
    "\n",
    "# 初始化网络和优化器\n",
    "model = CNN().to(device)\n",
    "criterion = nn.CrossEntropyLoss()\n",
    "optimizer = optim.SGD(model.parameters(), lr=0.001, momentum=0.9)\n",
    "\n",
    "# 训练网络\n",
    "num_epochs = 20\n",
    "train_losses = []\n",
    "test_accuracies = []\n",
    "\n",
    "for epoch in range(num_epochs):  # 循环多次\n",
    "    running_loss = 0.0\n",
    "    model.train()\n",
    "    for i, data in enumerate(trainloader, 0):\n",
    "        inputs, labels = data[0].to(device), data[1].to(device)\n",
    "\n",
    "        # 将梯度置零\n",
    "        optimizer.zero_grad()\n",
    "\n",
    "        # 前向+后向+优化\n",
    "        outputs = model(inputs)\n",
    "        loss = criterion(outputs, labels)\n",
    "        loss.backward()\n",
    "        optimizer.step()\n",
    "\n",
    "        # 累加损失\n",
    "        running_loss += loss.item()\n",
    "\n",
    "    avg_train_loss = running_loss / len(trainloader)\n",
    "    train_losses.append(avg_train_loss)\n",
    "\n",
    "    # 在测试集上评估网络\n",
    "    correct = 0\n",
    "    total = 0\n",
    "    model.eval()\n",
    "    with torch.no_grad():\n",
    "        for data in testloader:\n",
    "            images, labels = data[0].to(device), data[1].to(device)\n",
    "            outputs = model(images)\n",
    "            _, predicted = torch.max(outputs.data, 1)\n",
    "            total += labels.size(0)\n",
    "            correct += (predicted == labels).sum().item()\n",
    "\n",
    "    test_accuracy = 100 * correct / total\n",
    "    test_accuracies.append(test_accuracy)\n",
    "\n",
    "    # 记录每个 epoch 的平均损失和测试集准确率\n",
    "    logger.info(f'Epoch [{epoch + 1}/{num_epochs}], Loss: {avg_train_loss:.4f}, Test Accuracy: {test_accuracy:.2f} %')\n",
    "    running_loss = 0.0\n",
    "\n",
    "print('Finished Training')\n",
    "\n",
    "# 绘制训练损失曲线\n",
    "epochs = range(1, num_epochs + 1)\n",
    "plt.figure(figsize=(10, 5))\n",
    "\n",
    "plt.plot(epochs, train_losses, 'bo-', label='Training Loss')\n",
    "plt.xlabel('Epoch')\n",
    "plt.ylabel('Loss')\n",
    "plt.title('Training Loss')\n",
    "plt.legend()\n",
    "\n",
    "plt.tight_layout()\n",
    "plt.show()\n",
    "\n",
    "# 输出最终测试集准确率\n",
    "final_accuracy = test_accuracies[-1]\n",
    "print(f'Final Test Accuracy: {final_accuracy:.2f} %')\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "1a81a22b-c3bc-4d44-a4a7-fe2d131c7a04",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Device: cuda:0\n",
      "Files already downloaded and verified\n",
      "Files already downloaded and verified\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "2024-06-03 17:35:24,802 - Epoch [1/20], Loss: 1.4344, Test Accuracy: 61.99 %\n",
      "2024-06-03 17:35:36,465 - Epoch [2/20], Loss: 1.0245, Test Accuracy: 67.60 %\n",
      "2024-06-03 17:35:47,989 - Epoch [3/20], Loss: 0.8556, Test Accuracy: 72.62 %\n",
      "2024-06-03 17:35:59,796 - Epoch [4/20], Loss: 0.7564, Test Accuracy: 74.15 %\n",
      "2024-06-03 17:36:11,385 - Epoch [5/20], Loss: 0.6917, Test Accuracy: 75.74 %\n",
      "2024-06-03 17:36:23,401 - Epoch [6/20], Loss: 0.6367, Test Accuracy: 76.30 %\n",
      "2024-06-03 17:36:34,912 - Epoch [7/20], Loss: 0.5860, Test Accuracy: 76.78 %\n",
      "2024-06-03 17:36:46,517 - Epoch [8/20], Loss: 0.5481, Test Accuracy: 77.70 %\n",
      "2024-06-03 17:36:58,226 - Epoch [9/20], Loss: 0.5075, Test Accuracy: 78.67 %\n",
      "2024-06-03 17:37:09,805 - Epoch [10/20], Loss: 0.4721, Test Accuracy: 79.39 %\n",
      "2024-06-03 17:37:21,550 - Epoch [11/20], Loss: 0.4408, Test Accuracy: 79.35 %\n",
      "2024-06-03 17:37:33,601 - Epoch [12/20], Loss: 0.4187, Test Accuracy: 79.21 %\n",
      "2024-06-03 17:37:45,194 - Epoch [13/20], Loss: 0.3814, Test Accuracy: 80.31 %\n",
      "2024-06-03 17:37:56,695 - Epoch [14/20], Loss: 0.3598, Test Accuracy: 80.83 %\n",
      "2024-06-03 17:38:08,277 - Epoch [15/20], Loss: 0.3356, Test Accuracy: 80.73 %\n",
      "2024-06-03 17:38:19,923 - Epoch [16/20], Loss: 0.3134, Test Accuracy: 80.25 %\n",
      "2024-06-03 17:38:31,440 - Epoch [17/20], Loss: 0.2984, Test Accuracy: 80.36 %\n",
      "2024-06-03 17:38:43,151 - Epoch [18/20], Loss: 0.2759, Test Accuracy: 81.07 %\n",
      "2024-06-03 17:38:55,108 - Epoch [19/20], Loss: 0.2554, Test Accuracy: 80.76 %\n",
      "2024-06-03 17:39:06,938 - Epoch [20/20], Loss: 0.2376, Test Accuracy: 81.41 %\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Finished Training\n"
     ]
    },
    {
     "data": {
      "image/png": "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rnp1cxb1EyfMbcMG5+dDQqTrrssfxhs1kiIjS79uAABKC6EbAAB4TPv25jXbx47ln0hNcr6m++xZc83wffukvXvzbg8cMIeu795tbleqXbvgMF6v3tX1jrPEGQCgNDC8HAAAeNTixebs5ZJz8HZ39nK73bw2/Mowvm+fGYhdCQ01e8evDOONGklF/QrAEmcAgKJwTbcLhG4AALyvoBAbFydNmXJ1ITYz0wzfVwby/ful7GzXx0VHF3zteN260tKlLHEGACgaodsFQjcAANbw5nBtu106fLjg3vHUVNfHhYZKOTkscQYAKBqh2wVCNwAA5Vt6utkTfmUYP3Cg8N7xy61bJ912myerBAD4OkK3C4RuAABQELtdeucd6ckni24bFyf16SN16iR16CBVruz5+gAAvsXdbBngxZpcmjZtmuLj4xUWFqbExERt3rzZrePmzZsnm82mnj17erZAAABQ5gUGSs2bu9f26FHzevTu3aWqVaV27aTx46WkJCkry4NFAgD8juWhe/78+RozZowmTpyobdu2KSEhQV26dNGJEycKPe7QoUN6+umn1b59ey9VCgAAyrrcJc5yJ027ks0m1akjzZ0rPfyw1KCB2UO+aZP08stSx45SlSrSHXdIr74q/fCD+TwAoPyyfHh5YmKiWrduralTp0qScnJyFBcXp5EjR2rcuHEFHmO323XrrbfqwQcf1Ndff6309HQtXbrUra/H8HIAAFCY4i5xdviwtHatuX31Vf6J2qpUMa//7tTJ3Bo3dh3qAQD+wy+Gl2dnZ2vr1q3q3LmzY19AQIA6d+6sTZs2uTzuxRdfVK1atfSXv/ylyK+RlZWlzMxMpw0AAMCV3r3NYB0T47w/Nrbg5cLq1ZMefFCaPVs6flzavVt6+22pRw8pMtKcuG3pUmnkSOn6683z3n+/NHOmuf44AKBsC7Lyi588eVJ2u11RUVFO+6OiorR3794Cj/nmm2/04YcfaseOHW59jUmTJumFF1642lIBAEA50ru3GZqLu8SZzWYG6+uvN0P2pUvStm1mD/jatdI335jnmz3b3CTp2mvNHvDbbze3GjU8//oAAN5jaegurtOnT+uBBx7QBx98oBpu/kR65plnNGbMGMfjzMxMxcXFeapEAABQRgQGXv2yYEFBUps25jZunHThgnn9d+5w9B9+kA4eNLf33jOPSUjIG4p+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qWJI0vPPP5/vPWjcuHGhxyxcuFCNGzdWWFiYmjZtquXLl3upWuSKj4/P977ZbDYNHz68wPZ81qyxYcMGde/eXXXq1JHNZtPSpUudnjcMQxMmTFB0dLQqVKigzp0768CBA0Wed9q0aYqPj1dYWJgSExO1efNmD72C8qmw9+3ixYsaO3asmjZtqooVK6pOnToaPHiwjh8/Xug5S/K9FsVT1Odt6NCh+d6Drl27FnlePm+eVdT7VtDPOpvNptdee83lOfm8eZY7v/NfuHBBw4cPV/Xq1VWpUiX16dNHaWlphZ63pD8TrUDohmXWr1+v4cOH67vvvtPq1at18eJF3XnnnTp79myhx0VERCglJcWxHT582EsVI9cNN9zg9B588803Ltt+++23GjBggP7yl79o+/bt6tmzp3r27Kldu3Z5sWL88MMPTu/Z6tWrJUl//vOfXR7DZ837zp49q4SEBE2bNq3A5//xj3/o7bff1owZM/T999+rYsWK6tKliy5cuODynPPnz9eYMWM0ceJEbdu2TQkJCerSpYtOnDjhqZdR7hT2vp07d07btm3T+PHjtW3bNi1evFj79u3TvffeW+R5i/O9FsVX1OdNkrp27er0HsydO7fQc/J587yi3rfL36+UlBR99NFHstls6tOnT6Hn5fPmOe78zv/kk0/qv//9rxYuXKj169fr+PHj6t27d6HnLcnPRMsYgI84ceKEIclYv369yzYzZ840IiMjvVcU8pk4caKRkJDgdvu+ffsad999t9O+xMRE45FHHinlylAco0aNMho0aGDk5OQU+DyfNetJMpYsWeJ4nJOTY9SuXdt47bXXHPvS09ON0NBQY+7cuS7P06ZNG2P48OGOx3a73ahTp44xadIkj9Rd3l35vhVk8+bNhiTj8OHDLtsU93strk5B79uQIUOMHj16FOs8fN68y53PW48ePYzbb7+90DZ83rzryt/509PTjeDgYGPhwoWONnv27DEkGZs2bSrwHCX9mWgVerrhMzIyMiRJ1apVK7TdmTNnVK9ePcXFxalHjx7avXu3N8rDZQ4cOKA6derommuu0aBBg3TkyBGXbTdt2qTOnTs77evSpYs2bdrk6TLhQnZ2tj799FM9+OCDstlsLtvxWfMtycnJSk1Ndfo8RUZGKjEx0eXnKTs7W1u3bnU6JiAgQJ07d+YzaKGMjAzZbDZVqVKl0HbF+V4Lz0hKSlKtWrXUqFEjPfbYY/r9999dtuXz5nvS0tL0xRdf6C9/+UuRbfm8ec+Vv/Nv3bpVFy9edPrsNG7cWHXr1nX52SnJz0QrEbrhE3JycjR69GjdcsstuvHGG122a9SokT766CN99tln+vTTT5WTk6N27drp119/9WK15VtiYqJmzZqllStX6t1331VycrLat2+v06dPF9g+NTVVUVFRTvuioqKUmprqjXJRgKVLlyo9PV1Dhw512YbPmu/J/cwU5/N08uRJ2e12PoM+5MKFCxo7dqwGDBigiIgIl+2K+70Wpa9r1676+OOPtXbtWk2ePFnr169Xt27dZLfbC2zP5833/Pvf/1blypWLHKbM5817CvqdPzU1VSEhIfn+EFnYZ6ckPxOtFGR1AYAkDR8+XLt27Sry+pm2bduqbdu2jsft2rVTkyZN9N577+mll17ydJmQ1K1bN8f9Zs2aKTExUfXq1dOCBQvc+ksyrPfhhx+qW7duqlOnjss2fNaA0nfx4kX17dtXhmHo3XffLbQt32ut179/f8f9pk2bqlmzZmrQoIGSkpLUqVMnCyuDuz766CMNGjSoyIlA+bx5j7u/85c19HTDciNGjNDnn3+udevWKTY2tljHBgcHq0WLFjp48KCHqkNRqlSpooYNG7p8D2rXrp1v9sm0tDTVrl3bG+XhCocPH9aaNWv00EMPFes4PmvWy/3MFOfzVKNGDQUGBvIZ9AG5gfvw4cNavXp1ob3cBSnqey0875prrlGNGjVcvgd83nzL119/rX379hX7553E581TXP3OX7t2bWVnZys9Pd2pfWGfnZL8TLQSoRuWMQxDI0aM0JIlS/TVV1+pfv36xT6H3W7Xzp07FR0d7YEK4Y4zZ87o559/dvketG3bVmvXrnXat3r1aqdeVHjPzJkzVatWLd19993FOo7PmvXq16+v2rVrO32eMjMz9f3337v8PIWEhKhly5ZOx+Tk5Gjt2rV8Br0oN3AfOHBAa9asUfXq1Yt9jqK+18Lzfv31V/3+++8u3wM+b77lww8/VMuWLZWQkFDsY/m8la6ifudv2bKlgoODnT47+/bt05EjR1x+dkryM9FSFk/khnLsscceMyIjI42kpCQjJSXFsZ07d87R5oEHHjDGjRvnePzCCy8Yq1atMn7++Wdj69atRv/+/Y2wsDBj9+7dVryEcumpp54ykpKSjOTkZGPjxo1G586djRo1ahgnTpwwDCP/e7Zx40YjKCjIeP311409e/YYEydONIKDg42dO3da9RLKLbvdbtStW9cYO3Zsvuf4rPmG06dPG9u3bze2b99uSDLefPNNY/v27Y5Zrl999VWjSpUqxmeffWb89NNPRo8ePYz69esb58+fd5zj9ttvN9555x3H43nz5hmhoaHGrFmzjP/973/Gww8/bFSpUsVITU31+usrqwp737Kzs417773XiI2NNXbs2OH08y4rK8txjivft6K+1+LqFfa+nT592nj66aeNTZs2GcnJycaaNWuMm266ybjuuuuMCxcuOM7B5837ivo+aRiGkZGRYYSHhxvvvvtugefg8+Zd7vzO/+ijjxp169Y1vvrqK2PLli1G27ZtjbZt2zqdp1GjRsbixYsdj935megrCN2wjKQCt5kzZzradOjQwRgyZIjj8ejRo426desaISEhRlRUlHHXXXcZ27Zt837x5Vi/fv2M6OhoIyQkxIiJiTH69etnHDx40PH8le+ZYRjGggULjIYNGxohISHGDTfcYHzxxRderhqGYRirVq0yJBn79u3L9xyfNd+wbt26Ar8v5r43OTk5xvjx442oqCgjNDTU6NSpU773s169esbEiROd9r3zzjuO97NNmzbGd99956VXVD4U9r4lJye7/Hm3bt06xzmufN+K+l6Lq1fY+3bu3DnjzjvvNGrWrGkEBwcb9erVM/7617/mC8983ryvqO+ThmEY7733nlGhQgUjPT29wHPwefMud37nP3/+vPH4448bVatWNcLDw41evXoZKSkp+c5z+THu/Ez0FTbDMAzP9KEDAAAAAFC+cU03AAAAAAAeQugGAAAAAMBDCN0AAAAAAHgIoRsAAAAAAA8hdAMAAAAA4CGEbgAAAAAAPITQDQAAAACAhxC6AQAAAADwEEI3AAAoNTabTUuXLrW6DAAAfAahGwCAMmLo0KGy2Wz5tq5du1pdGgAA5VaQ1QUAAIDS07VrV82cOdNpX2hoqEXVAAAAeroBAChDQkNDVbt2baetatWqksyh3++++666deumChUq6JprrtGiRYucjt+5c6duv/12VahQQdWrV9fDDz+sM2fOOLX56KOPdMMNNyg0NFTR0dEaMWKE0/MnT55Ur169FB4eruuuu07Lli3z7IsGAMCHEboBAChHxo8frz59+ujHH3/UoEGD1L9/f+3Zs0eSdPbsWXXp0kVVq1bVDz/8oIULF2rNmjVOofrdd9/V8OHD9fDDD2vnzp1atmyZrr32Wqev8cILL6hv37766aefdNddd2nQoEE6deqUV18nAAC+wmYYhmF1EQAA4OoNHTpUn376qcLCwpz2P/vss3r22Wdls9n06KOP6t1333U8d/PNN+umm27S9OnT9cEHH2js2LE6evSoKlasKElavny5unfvruPHjysqKkoxMTEaNmyYXn755QJrsNlseu655/TSSy9JMoN8pUqVtGLFCq4tBwCUS1zTDQBAGdKxY0enUC1J1apVc9xv27at03Nt27bVjh07JEl79uxRQkKCI3BL0i233KKcnBzt27dPNptNx48fV6dOnQqtoVmzZo77FStWVEREhE6cOFHSlwQAgF8jdAMAUIZUrFgx33Dv0lKhQgW32gUHBzs9ttlsysnJ8URJAAD4PK7pBgCgHPnuu+/yPW7SpIkkqUmTJvrxxx919uxZx/MbN25UQECAGjVqpMqVKys+Pl5r1671as0AAPgzeroBAChDsrKylJqa6rQvKChINWrUkCQtXLhQrVq10p/+9CfNnj1bmzdv1ocffihJGjRokCZOnKghQ4bo+eef12+//aaRI0fqgQceUFRUlCTp+eef16OPPqpatWqpW7duOn36tDZu3KiRI0d694UCAOAnCN0AAJQhK1euVHR0tNO+Ro0aae/evZLMmcXnzZunxx9/XNHR0Zo7d66uv/56SVJ4eLhWrVqlUaNGqXXr1goPD1efPn305ptvOs41ZMgQXbhwQf/85z/19NNPq0aNGrrvvvu89wIBAPAzzF4OAEA5YbPZtGTJEvXs2dPqUgAAKDe4phsAAAAAAA8hdAMAAAAA4CFc0w0AQDnBFWUAAHgfPd0AAAAAAHgIoRsAAAAAAA8hdAMAAAAA4CGEbgAAAAAAPITQDQAAAACAhxC6AQAAAADwEEI3AAAAAAAeQugGAAAAAMBDCN0AAAAAAHjI/w8BE1QA19K9DgAAAABJRU5ErkJggg==",
      "text/plain": [
       "<Figure size 1000x500 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Final Test Accuracy: 81.41 %\n"
     ]
    }
   ],
   "source": [
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.nn.functional as F\n",
    "import torch.optim as optim\n",
    "import torchvision\n",
    "import torchvision.transforms as transforms\n",
    "import matplotlib.pyplot as plt\n",
    "import logging\n",
    "\n",
    "# 检查 GPU 是否可用\n",
    "device = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\n",
    "print(\"Device:\", device)\n",
    "\n",
    "# 设置日志\n",
    "logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(message)s')\n",
    "logger = logging.getLogger()\n",
    "\n",
    "# 定义 CNN 网络\n",
    "class CNN(nn.Module):\n",
    "    def __init__(self, k):\n",
    "        super(CNN, self).__init__()\n",
    "        \n",
    "        self.conv1 = nn.Sequential(\n",
    "            nn.Conv2d(3, 32, kernel_size=3, padding=1),\n",
    "            nn.ReLU(),\n",
    "            nn.BatchNorm2d(32),\n",
    "            nn.Conv2d(32, 32, kernel_size=3, padding=1),\n",
    "            nn.ReLU(),\n",
    "            nn.BatchNorm2d(32),\n",
    "            nn.MaxPool2d(2),\n",
    "        )\n",
    "        self.conv2 = nn.Sequential(\n",
    "            nn.Conv2d(32, 64, kernel_size=3, padding=1),\n",
    "            nn.ReLU(),\n",
    "            nn.BatchNorm2d(64),\n",
    "            nn.Conv2d(64, 64, kernel_size=3, padding=1),\n",
    "            nn.ReLU(),\n",
    "            nn.BatchNorm2d(64),\n",
    "            nn.MaxPool2d(2),\n",
    "        )\n",
    "        self.conv3 = nn.Sequential(\n",
    "            nn.Conv2d(64, 128, kernel_size=3, padding=1),\n",
    "            nn.ReLU(),\n",
    "            nn.BatchNorm2d(128),\n",
    "            nn.Conv2d(128, 128, kernel_size=3, padding=1),\n",
    "            nn.ReLU(),\n",
    "            nn.BatchNorm2d(128),\n",
    "            nn.MaxPool2d(2),\n",
    "        )\n",
    "        \n",
    "        self.fc1 = nn.Linear(128*4*4, 1024)\n",
    "        self.dropout = nn.Dropout(p=0.25)\n",
    "        self.fc2 = nn.Linear(1024, k)\n",
    "        \n",
    "    def forward(self, x):\n",
    "        x = self.conv1(x)\n",
    "        x = self.conv2(x)\n",
    "        x = self.conv3(x)\n",
    "        x = x.view(x.size(0), -1)\n",
    "        x = F.dropout(x, p=0.5, training=self.training)\n",
    "        x = self.fc1(x)\n",
    "        x = F.dropout(x, p=0.2, training=self.training)\n",
    "        x = self.fc2(x)\n",
    "        return x\n",
    "\n",
    "# 加载 CIFAR-10 数据集\n",
    "transform = transforms.Compose(\n",
    "    [transforms.ToTensor(),\n",
    "     transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])\n",
    "\n",
    "trainset = torchvision.datasets.CIFAR10(root='./data', train=True,\n",
    "                                        download=True, transform=transform)\n",
    "trainloader = torch.utils.data.DataLoader(trainset, batch_size=100,\n",
    "                                          shuffle=True, num_workers=2)\n",
    "\n",
    "testset = torchvision.datasets.CIFAR10(root='./data', train=False,\n",
    "                                       download=True, transform=transform)\n",
    "testloader = torch.utils.data.DataLoader(testset, batch_size=100,\n",
    "                                         shuffle=False, num_workers=2)\n",
    "\n",
    "# 初始化网络和优化器\n",
    "model = CNN(10).to(device)\n",
    "criterion = nn.CrossEntropyLoss()\n",
    "optimizer = optim.SGD(model.parameters(), lr=0.001, momentum=0.9)\n",
    "\n",
    "# 训练网络\n",
    "num_epochs = 20\n",
    "train_losses = []\n",
    "test_accuracies = []\n",
    "\n",
    "for epoch in range(num_epochs):  # 循环多次\n",
    "    running_loss = 0.0\n",
    "    model.train()\n",
    "    for i, data in enumerate(trainloader, 0):\n",
    "        inputs, labels = data[0].to(device), data[1].to(device)\n",
    "\n",
    "        # 将梯度置零\n",
    "        optimizer.zero_grad()\n",
    "\n",
    "        # 前向+后向+优化\n",
    "        outputs = model(inputs)\n",
    "        loss = criterion(outputs, labels)\n",
    "        loss.backward()\n",
    "        optimizer.step()\n",
    "\n",
    "        # 累加损失\n",
    "        running_loss += loss.item()\n",
    "\n",
    "    avg_train_loss = running_loss / len(trainloader)\n",
    "    train_losses.append(avg_train_loss)\n",
    "\n",
    "    # 在测试集上评估网络\n",
    "    correct = 0\n",
    "    total = 0\n",
    "    model.eval()\n",
    "    with torch.no_grad():\n",
    "        for data in testloader:\n",
    "            images, labels = data[0].to(device), data[1].to(device)\n",
    "            outputs = model(images)\n",
    "            _, predicted = torch.max(outputs.data, 1)\n",
    "            total += labels.size(0)\n",
    "            correct += (predicted == labels).sum().item()\n",
    "\n",
    "    test_accuracy = 100 * correct / total\n",
    "    test_accuracies.append(test_accuracy)\n",
    "\n",
    "    # 记录每个 epoch 的平均损失和测试集准确率\n",
    "    logger.info(f'Epoch [{epoch + 1}/{num_epochs}], Loss: {avg_train_loss:.4f}, Test Accuracy: {test_accuracy:.2f} %')\n",
    "    running_loss = 0.0\n",
    "\n",
    "print('Finished Training')\n",
    "\n",
    "# 绘制训练损失曲线\n",
    "epochs = range(1, num_epochs + 1)\n",
    "plt.figure(figsize=(10, 5))\n",
    "\n",
    "plt.plot(epochs, train_losses, 'bo-', label='Training Loss')\n",
    "plt.xlabel('Epoch')\n",
    "plt.ylabel('Loss')\n",
    "plt.title('Training Loss')\n",
    "plt.legend()\n",
    "\n",
    "plt.tight_layout()\n",
    "plt.show()\n",
    "\n",
    "# 输出最终测试集准确率\n",
    "final_accuracy = test_accuracies[-1]\n",
    "print(f'Final Test Accuracy: {final_accuracy:.2f} %')\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a8d65742-9f23-4665-9033-c19e6551ca1d",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
